<?php


namespace Cumulon\Service\Auth;


use Exception;
use \Firebase\JWT\JWT;
use Illuminate\Support\Facades\Cache;
use Cumulon\Service\Kernel\Http\Client;
use Cumulon\Service\Kernel\Http\Exceptions\JwtException;
use Cumulon\Service\Kernel\Concerns\InteractsWithCache;

class AuthClient extends Client
{
    use InteractsWithCache;
    /**
     * @param string $token
     * @return array
     * @throws JwtException
     */
    public function verifyToken(string $token){
        try{
            JWT::$leeway = 60;
            return JWT::decode($token, $this->app['config']->get('app_key'), array('HS256'));
        }catch(\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
            throw new JwtException($e->getMessage());

        }catch(\Firebase\JWT\BeforeValidException $e) {  // 签名在某个时间点之后才能用
            throw new JwtException($e->getMessage());

        }catch(\Firebase\JWT\ExpiredException $e) {  // token过期
            throw new JwtException($e->getMessage());

        }catch(Exception $e) {  //其他错误
            throw new JwtException($e->getMessage());
        }
    }

    /**
     *  解密并且签发一下新的登录token
     * @param string $token
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws JwtException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function decodeToken(string $token){
        $result = $this->verifyToken($token);
        if(!is_array($result)){
            try{
                $user = $this->getUser($result->data->access_token);
                if(isset($user['errmsg'])){
                    return $user;
                }
                $new_token = $this->encode([
                    'id'=>$user['id'],
                    'username' => $user['username'],
                    'mobile' => $user['mobile']
                ],$result->data->exp);
                Cache::add($new_token, $result->data->access_token, $result->data->exp); //回调解析过来的 全局 token  保存起来便于获取其他信息使用
                return [
                    'access_token' => $new_token,
                    "token_type"=> "bearer",
                    "expires_in"=> $result->data->exp - time()
                ];
            }catch (Exception $exception){
                return ['errcode'=>400,'errmsg'=>$exception->getMessage()];
            }

        }
        return $result;
    }

    /**
     * @param array $data
     * @param string $exp
     * @return
     */
    public function encode(array $data,string $exp){

        $key = $this->app['config']->get('app_key'); //key
        $time = time(); //当前时间
        $token = [
            'iss' => '', //签发者 可选
            'aud' => '', //接收该JWT的一方，可选
            'iat' => $time, //签发时间
            'nbf' => $time , //(Not Before)：某个时间点后才能访问，比如设置time+30，表示当前时间30秒后才能使用
            'exp' => $exp, //过期时间,这里设置2个小时
            'data' => $data
        ];
        return JWT::encode($token, $key); //输出Token
    }

    /**
     * @param string $token
     * @return
     * @throws Exception
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getUser(string $token){
        $query = [
            'token' => $token
        ];
        return  $this->get('/api/user/info', $query);
    }
}